package com.dingup.mock.controller.file;


import com.dingup.api.base.HttpResContent;
import com.dingup.mock.enums.FileUploadSceneTypeEnum;
import com.dingup.mock.util.ConstUtil;
import com.dingup.util.GConstUtil;
import com.dingup.util.GOssUtil;
import com.dingup.util.GStrUtil;
import com.suyeer.basic.util.BHttpResUtil;
import com.suyeer.basic.util.BLogUtil;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import static com.dingup.api.base.BaseUtil.saveErrorMsgAndData;
import static com.dingup.api.base.BaseUtil.saveSuccessMsgAndData;
import static com.dingup.mock.util.ConstUtil.*;


/**
 * Created by yanggavin on 16/5/20.
 */
@Controller
@RequestMapping("/file")
public class FileController {
    private final String OSS_BUCKET_NAME = "onlinetest-public";
    private final String OSS_BUCKET_KEY_FOLDER_PART = "speaking/user_data";
    private final String OSS_BUCKET_KEY_FOLDER_PART_FOR_HOMEWORK_AUDIO = "homework/audio";
    private final String OSS_BUCKET_KEY_FOLDER_PART_FOR_HOMEWORK_DOC = "homework/doc";
    private final String OSS_BUCKET_KEY_FOLDER_PART_FOR_HOMEWORK_IMG = "homework/img";
    private final String OSS_BUCKET_KEY_FOLDER_PART_FOR_WX_COURSE_AUDIO = "wx_course/audio";
    private final String OSS_BUCKET_KEY_FOLDER_PART_FOR_WX_COURSE_IMG = "wx_course/img";
    private final String OSS_BUCKET_KEY_FOLDER_PART_FOR_WX_COURSE_DOC = "wx_course/doc";
    private final String OSS_BUCKET_KEY_FOLDER_PART_FOR_WX_COURSE_PDF = "wx_course/pdf";



    /**
     * 为H5提交音频文件提供保存接口
     * @param multipartFile
     * @param request
     * @param response
     */
    @RequestMapping(value = "/upload_file.do", method = RequestMethod.POST)
    public void uploadFile(@RequestParam(ConstUtil.REQUEST_PARAMETER_FILE) MultipartFile multipartFile,
                           HttpServletRequest request,
                           HttpServletResponse response){
        HttpResContent<String> hrc = new HttpResContent<>(request, response);
        hrc.setFuncDes("H5方式上传文件");
        try {
            // check.
            checkUploadFileParaValid(multipartFile);
            // do.
            String ossFileName, ossBucketKeyFolderPart = "", ossBucketName = OSS_BUCKET_NAME;
            FileUploadSceneTypeEnum sceneType = FileUploadSceneTypeEnum.DEFAULT;
            String sceneTypeVal = request.getParameter(ConstUtil.REQUEST_PARAMETER_SCENE_TYPE);
            if (StringUtils.isNotBlank(sceneTypeVal)){
                sceneType = Enum.valueOf(FileUploadSceneTypeEnum.class, sceneTypeVal.toUpperCase());
            }
            // ossBucketName.
            if (FileUploadSceneTypeEnum.DEFAULT == sceneType){ // 模考口语录音场景 + 入学测试口语录音场景
                ossFileName = String.format("%s%s%s", SPEAKING_ANSWER_FILE_PREFIX, GStrUtil.getRandomStr(8), FILE_EXT_NAME_WAV);
                ossBucketKeyFolderPart = OSS_BUCKET_KEY_FOLDER_PART;
            } else {
                // 默认情景，及口语录音情景下，上传的文件名为固定的file，不含有扩展名.
                String fileType = getFileTypeName(multipartFile.getOriginalFilename());
                // ossFileName.
                String ossFileNamePrefix = "", ossFileNamePart = GStrUtil.getRandomStr(10);
                if (FileUploadSceneTypeEnum.HOMEWORK == sceneType){
                    ossFileNamePrefix = HOMEWORK_FILE_PREFIX;
                } else if (FileUploadSceneTypeEnum.WX_COURSE == sceneType){
                    if (fileType.equalsIgnoreCase(FILE_EXT_NAME_DOC) || fileType.equalsIgnoreCase(FILE_EXT_NAME_DOCX)
                            || fileType.equalsIgnoreCase(FILE_EXT_NAME_PDF)){
                        ossFileNamePart = getFileName(multipartFile.getOriginalFilename()) + "_" + GStrUtil.getRandomStr(2);
                    } else {
                        ossFileNamePrefix = WX_COURSE_FILE_PREFIX;
                    }
                }
                ossFileName = String.format("%s%s%s", ossFileNamePrefix, ossFileNamePart, fileType);
                // ossBucketKeyFolderPart.
                // 根据文件类型及场景类型来区分不同目录文件结构.
                if (fileType.equalsIgnoreCase(FILE_EXT_NAME_WAV) || fileType.equalsIgnoreCase(FILE_EXT_NAME_MP3)
                        || fileType.equalsIgnoreCase(FILE_EXT_NAME_M4A)){
                    if (FileUploadSceneTypeEnum.HOMEWORK == sceneType){
                        ossBucketKeyFolderPart = OSS_BUCKET_KEY_FOLDER_PART_FOR_HOMEWORK_AUDIO;
                    } else if (FileUploadSceneTypeEnum.WX_COURSE == sceneType){
                        ossBucketKeyFolderPart = OSS_BUCKET_KEY_FOLDER_PART_FOR_WX_COURSE_AUDIO;
                    }
                } else if (fileType.equalsIgnoreCase(FILE_EXT_NAME_DOC) || fileType.equalsIgnoreCase(FILE_EXT_NAME_DOCX)){
                    if (FileUploadSceneTypeEnum.HOMEWORK == sceneType){
                        ossBucketKeyFolderPart = OSS_BUCKET_KEY_FOLDER_PART_FOR_HOMEWORK_DOC;
                    } else if (FileUploadSceneTypeEnum.WX_COURSE == sceneType){
                        ossBucketKeyFolderPart = OSS_BUCKET_KEY_FOLDER_PART_FOR_WX_COURSE_DOC;
                    }
                } else if (fileType.equalsIgnoreCase(FILE_EXT_NAME_JPG) || fileType.equalsIgnoreCase(FILE_EXT_NAME_JPEG)
                        || fileType.equalsIgnoreCase(FILE_EXT_NAME_PNG)){
                    if (FileUploadSceneTypeEnum.WX_COURSE == sceneType){
                        ossBucketKeyFolderPart = OSS_BUCKET_KEY_FOLDER_PART_FOR_WX_COURSE_IMG;
                    }
                    if (FileUploadSceneTypeEnum.HOMEWORK == sceneType){
                        ossBucketKeyFolderPart = OSS_BUCKET_KEY_FOLDER_PART_FOR_HOMEWORK_IMG;
                    }
                } else if (fileType.equalsIgnoreCase(FILE_EXT_NAME_PDF)){
                    if (FileUploadSceneTypeEnum.WX_COURSE == sceneType){
                        ossBucketKeyFolderPart = OSS_BUCKET_KEY_FOLDER_PART_FOR_WX_COURSE_PDF;
                    }
                    if (FileUploadSceneTypeEnum.HOMEWORK == sceneType){
                        ossBucketKeyFolderPart = OSS_BUCKET_KEY_FOLDER_PART_FOR_HOMEWORK_IMG;
                    }
                }
                BLogUtil.info("{}-{}-{}-{}-{}", ossFileName, ossBucketKeyFolderPart, ossBucketName, fileType, sceneType);
            }
            // ossUrl.
            String ossUrl = uploadFileToOss(multipartFile, ossFileName, ossBucketKeyFolderPart, ossBucketName);

            if (StringUtils.isBlank(ossUrl)){
                throw new Exception("上传文件到OSS服务器失败:" + ossFileName);
            }
            // response.
            saveSuccessMsgAndData(hrc, ossUrl);
        } catch (Exception e){
            e.printStackTrace();
            saveErrorMsgAndData(hrc, e);
        } finally {
            BHttpResUtil.writeResult(hrc);
        }
    }

    /**
     * 为Flash控件通过form提交音频文件提供保存接口
     * @param request
     * @param response
     */
    @RequestMapping(value="/upload_flash_file.do", method = RequestMethod.POST)
    public void upload(MultipartHttpServletRequest request, HttpServletResponse response) {
        HttpResContent<String> hrc = new HttpResContent<>(request, response);
        hrc.setFuncDes("flash插件录制的音频文件上传");
        try {
            MultipartFile mf = request.getFile("upload_file[filename]");
            saveSuccessMsgAndData(hrc, updateFileToOss(mf));
        } catch (Exception e){
            saveErrorMsgAndData(hrc, e);
        } finally {
            BHttpResUtil.writeResult(hrc);
        }
    }

    /**
     * 将multipartFile中的音频文件保存到OSS服务器,并返回文件url
     * @param mf
     * @return
     * @throws Exception
     */
    private String updateFileToOss(MultipartFile mf) throws Exception {
        checkUploadFileParaValid(mf);
        String ossFileName = String.format("%s%s%s", SPEAKING_ANSWER_FILE_PREFIX, GStrUtil.getRandomStr(8), FILE_EXT_NAME_WAV);
        String ossUrl = GOssUtil.putObjectToOss(mf.getInputStream(),
                mf.getSize(),
                mf.getContentType(),
                OSS_BUCKET_KEY_FOLDER_PART,
                ossFileName,
                OSS_BUCKET_NAME);
        // 替换为https链接
        ossUrl = GOssUtil.replaceHttpToHttps(ossUrl);
        if (StringUtils.isBlank(ossUrl)) {
            throw new Exception("保存到oss操作失败");
        }
        return ossUrl;
    }

    /**
     * 将multipartFile中的音频文件保存到OSS服务器,并返回文件url
     * @param mf
     * @return
     * @throws Exception
     */
    private String uploadFileToOss(MultipartFile mf, String ossFileName, String ossBucketKeyFolderPart, String ossBucketName) throws Exception {
        String retUrl = "";
        if (StringUtils.isNotBlank(ossFileName) && StringUtils.isNotBlank(ossBucketKeyFolderPart) && StringUtils.isNotBlank(ossBucketName)){
            retUrl = GOssUtil.putObjectToOss(mf.getInputStream(),
                    mf.getSize(),
                    mf.getContentType(),
                    ossBucketKeyFolderPart,
                    ossFileName,
                    ossBucketName);
            // 替换为https链接
            retUrl = GOssUtil.replaceHttpToHttps(retUrl);
            if (StringUtils.isBlank(retUrl)) {
                throw new Exception("保存到oss操作失败");
            }
        } else {
            throw new Exception("执行文件上传oss操作时参数错误");
        }
        return retUrl;
    }

    /**
     * 检查上传音频文件的参数信息
     * @param multipartFile
     * @throws Exception
     */
    private void checkUploadFileParaValid(MultipartFile multipartFile) throws Exception{
        if (multipartFile == null || multipartFile.getInputStream() == null){
            throw new IllegalArgumentException("上传文件为空");
        }
        if (multipartFile.getSize() > FILE_MAX_SIZE_ALLOWED * 1024 * 1024) {
            throw new IllegalArgumentException(String.format("文件太大，最大不能超过%dM", FILE_MAX_SIZE_ALLOWED));
        }
        String contentType = multipartFile.getContentType();
        if (!contentType.equalsIgnoreCase(GConstUtil.CONTENT_TYPE_AUDIO_WAV)
                && !contentType.equalsIgnoreCase(GConstUtil.CONTENT_TYPE_AUDIO_MP3)
                && !contentType.equalsIgnoreCase(GConstUtil.CONTENT_TYPE_AUDIO_M4A)
                && !contentType.equalsIgnoreCase(GConstUtil.CONTENT_TYPE_WORD_DOC)
                && !contentType.equalsIgnoreCase(GConstUtil.CONTENT_TYPE_WORD_DOCX)
                && !contentType.equalsIgnoreCase(GConstUtil.CONTENT_TYPE_WORD_PDF)
                && !contentType.equalsIgnoreCase(ConstUtil.CONTENT_TYPE_IMAGE_PNG)
                && !contentType.equalsIgnoreCase(GConstUtil.CONTENT_TYPE_IMAGE_JPEG)) {
            throw new IllegalArgumentException("非法文件类型");
        }
    }

    /**
     * 获取文件类型字符串
     * @param fileName
     * @return
     */
    private String getFileTypeName(String fileName){
        int index = fileName.lastIndexOf(".");
        // 如果文件名不含有扩展名，则认为是口语录音的上传文件，直接返回空
        return (index == -1 ? GConstUtil.STRING_EMPTY : fileName.substring(index));
    }

    /**
     * 获取文件名
     * @param fileName
     * @return
     */
    private String getFileName(String fileName){
        int index = fileName.indexOf(".");
        // 如果文件名不含有扩展名，则认为是口语录音的上传文件，直接返回文件名
        return (index == -1 ? fileName : fileName.substring(0, index));
    }
}
